package com.demo.search.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Transactional;

import com.demo.search.dao.SearchTaskDao;
import com.demo.search.engine.SearchEngine;
import com.demo.search.model.SearchTask;
import com.demo.search.model.SearchTask.Operate;
import com.demo.search.model.SearchTask.Status;
import com.demo.search.service.SearchTaskService;
import com.demo.search.support.SearchTaskSupport;

/**
 * 
 * 索引任务服务
 * @author ryuu.kk
 *
 */
public class BaseSearchTaskService implements SearchTaskService {

	/**
	 * 日志
	 */
	private static final Logger LOG = Logger.getLogger(BaseSearchTaskService.class);
	
	/**
	 * 索引处理引擎
	 */
	private SearchEngine engine;

	/**
	 * 索引任务Dao
	 */
	private SearchTaskDao searchTaskDao;
	
	/**
	 * 业务索引任务处理
	 */
	private List<SearchTaskSupport> searchTaskSupportList;
	
	@Override
	public List<SearchTask> findList(Long siteId, String targetType, Operate operate, Status status, Date begin, Date end) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("targetType", targetType);
		params.put("handleOpt", operate == null ? "" : operate.get());
		params.put("handleStatus", status == null ? "" : status.get());
		params.put("begin", begin);
		params.put("end", end);
		return searchTaskDao.select(params);
	}

	@Override
	public List<SearchTask> findList(Long siteId, Status status) {
		return findList(siteId, null, null, status, null, null);
	}

	@Override
	@Transactional
	public int process() throws IOException {
		return process(Status.Wait);
	}
		
	@Override
	@Transactional
	public int process(Status status) throws IOException {
		int cnt = 0;
		List<SearchTask> searchTaskList = findList(null, status);
		if (searchTaskList.size() > 0) {
			// 将任务分解后处理
			for(SearchTask task : searchTaskList) {
				if (searchTaskSupportList == null) {
					LOG.warn("searchTaskSupportList is empty.");
					return cnt;
				}
				for (SearchTaskSupport handle : searchTaskSupportList) {
					if (handle.support(task.getTargetType())) {
						//handle.process(task.getTargetId(), Operate.get(task.getHandleOpt()));
						Object target = handle.getTarget(task.getTargetId());
						
						if (target != null) {
							if (engine.support(target)) {
								Operate opt = Operate.get(task.getHandleOpt());
								switch(opt) {
								case Create:
									// 创建索引
									engine.createIndex(target);
									break;
								case Update:
									// 更新索引
									engine.updateIndex(target);
									break;
								case Delete:
									// 删除索引
									engine.deleteIndex(target);
									break;
								default:
									// other? no
								}
								// 后置处理:任务ID、状态
								afterProcess(task.getId(), Status.Finished);
							}
							cnt ++;
						} else {
							// 后置处理:任务ID、状态
							afterProcess(task.getId(), Status.Undo);
						}
					}
				}
			}
		}
		return cnt;
	}
	
	@Override
	public int processAll() throws IOException {
		int cnt = 0;
		for (SearchTaskSupport handle : searchTaskSupportList) {
			List<? extends Object>  targetList = handle.getTargetAll();
			for (Object target : targetList) {
				if (engine.support(target)) {
					// 创建索引
					engine.createIndex(target);
					// 后置处理
					//afterProcess(task.getId(), Status.Finished);
				}
			}
			cnt ++;
		}
		return cnt;
	}
	
	@Override
	public void addSupport(SearchTaskSupport support) {
		if (this.searchTaskSupportList == null) {
			searchTaskSupportList = new ArrayList<SearchTaskSupport>();
		}
		searchTaskSupportList.add(support);
	}
	
	protected void afterProcess(Long id, Status status) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("enter index after process. update SearchTask status [ id:" + id + " & status:" + status + " ]");
		}
		// 更新任务状态
		searchTaskDao.update(id, status);
	}
	
	
	public void setEngine(SearchEngine engine) {
		this.engine = engine;
	}
	
	public void setSearchTaskDao(SearchTaskDao searchTaskDao) {
		this.searchTaskDao = searchTaskDao;
	}

	public void setSearchTaskSupportList(List<SearchTaskSupport> searchTaskSupportList) {
		this.searchTaskSupportList = searchTaskSupportList;
	}
}
